package com.googlecode.gwtptk.client;

import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable;

/**
 * Simple custom layout component that places components into a grid with specified number of rows.
 * User then just adds other widgets or texts to the panel and added stuff flows according to the
 * width of the flow grid. User can set/increment column index when needed, if it is set beyond
 * flow grid width next widget will be added to the next row, column 0.
 * <p/>
 * Flow grid is not a Composite, it is still a FlexTable, so user can mess with it and go around
 * the interface - it is not designed to be bullet proof, just to help user with the simple case
 * - to provide simple meaningfull add functionality and let widgets flow accordingly.
 *
 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
 */
public class FlowGrid extends FlexTable {
	private int width;
	private int row = 0;
	private int column = 0;

	/**
	 * Creates the flow grid with specified width.
	 *
	 * @param width requested flow grid width
	 */
	public FlowGrid(int width) {
		this.width = width;
		setCellSpacing(5);
		this.addStyleName("flow-grid-style");
	}

	/**
	 * Adds a widget to the grid. If it would go beyond width on the same row, it is added to the
	 * beginning of the next row. Uses {@link #setWidget(int, int, com.google.gwt.user.client.ui.Widget)}
	 * internally.
	 *
	 * @param widget widget to be added
	 */
	public void add(Widget widget) {
		if (column >= width) {
			nextRow();
		}
		setWidget(row, column++, widget);
	}

	/**
	 * Adds a text to the grid. If it would go beyond width on the same row, it is added to the
	 * beginning of the next row. Uses {@link #setText(int, int, String)} internally.
	 *
	 * @param text text to be added
	 */
	public void add(String text) {
		if (column >= width) {
			nextRow();
		}
		setText(row, column++, text);
	}

	/**
	 * Sets the position to the beginning of the next row. Kinda "break line". :-)
	 */
	public void nextRow() {
		row++;
		column = 0;
	}

	/**
	 * Moves column index to the next position.
	 */
	public void nextColumn() {
		column++;
	}

	/**
	 * Sets the column for the next added widget (0 is the first column).
	 *
	 * @param column new current column index
	 */
	public void setColumn(int column) {
		this.column = column;
	}

	/**
	 * Returns the width of the flow grid.
	 *
	 * @return width of the flow grid
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * Returns the current row number for the next added widget (0 is the first row).
	 *
	 * @return current row number
	 */
	public int getRow() {
		return row;
	}

	/**
	 * Returns the current column number for the next added widget (0 is the first column).
	 *
	 * @return current column index
	 */
	public int getColumn() {
		return column;
	}

	/**
	 * Clears the flow grid and resets row and column.
	 */
	public void clear() {
		super.clear();
		row = 0;
		column = 0;
	}

	/**
	 * Sets all columns to the same width - typically chained after constructor call.
	 *
	 * @return this flow grid
	 */
	public FlowGrid setEqualColumnWidth() {
		for (int i = 0; i < width; i++) {
			this.getColumnFormatter().setWidth(i, (100d / width) + "%");
		}
		return this;
	}
}
